﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using FluentValidation.Results;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using FluentValidation;

namespace TestProject1 {
  /// <summary>
  /// Summary description for UnitTest1
  /// </summary>
  [TestClass]
  public class UnitTest1 {
    public UnitTest1() {
    }

    private TestContext testContextInstance;
    /*
        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext {
          get {
            return testContextInstance;
          }
          set {
            testContextInstance = value;
          }
        }

        #region Additional test attributes
        //
        // You can use the following additional attributes as you write your tests:
        //
        // Use ClassInitialize to run code before running the first test in the class
        // [ClassInitialize()]
        // public static void MyClassInitialize(TestContext testContext) { }
        //
        // Use ClassCleanup to run code after all tests in a class have run
        // [ClassCleanup()]
        // public static void MyClassCleanup() { }
        //
        // Use TestInitialize to run code before running each test 
        // [TestInitialize()]
        // public void MyTestInitialize() { }
        //
        // Use TestCleanup to run code after each test has run
        // [TestCleanup()]
        // public void MyTestCleanup() { }
        //
        #endregion

     */

    internal class y {
      public int x {
        get;
        set;
      }
      public string z {
        get;
        set;
      }
    }

    internal class a {
      public int x {
        get;
        set;
      }
      public string z {
        get;
        set;
      }
    }

    [TestMethod]
    public void TestMethod2() {
      var x = new y[4] 
      {
        new y() { x = 1, z = "2" }, 
        new y() { x = 2, z = "1" },
        new y() { x = 2, z = "1" },
        new y() { x = 2, z = "1" }
      };

      var b = x.Select<y, a>((o, e) =>
      {
        if (o.x > 1) {

          return new a() {
                           x = o.x,
                           z = o.z
                         };
        } else {
          return null;
        }
                             }).;

      for (int i = 0; i < x.Length; i++) {

      }

    }

    internal void TestMethod3(int[] x) {
      Console.WriteLine(x[1]);
    }


    [TestMethod]
    public void TestMethod1() {
      var genList = new GenericList<int>();
      var validate = new GenericValidator();
      var result = validate.Validate(genList);
      if (result.IsValid)
        return;

      foreach (var error in result.Errors) {
        Console.WriteLine("{0}", error.ErrorMessage);
      }
    }
  }

  internal class GenericValidator : AbstractValidator<GenericList<int>> {
    public GenericValidator() {

      RuleFor(x => x.x).NotNull().WithMessage("Can't be null");

    }
  }

  internal class Customer {
    public IList<Order> Orders {
      get;
      set;
    }
  }

  internal class Order {
    public string ProductName {
      get;
      set;
    }
    public decimal? Cost {
      get;
      set;
    }
  }



  // type parameter T in angle brackets
  public class GenericList<T> {

    public string x;

    // The nested class is also generic on T.
    private class Node {
      // T used in non-generic constructor.
      public Node(T t) {
        Next = null;
        Data = t;
      }

      public Node Next {
        get;
        set;
      }

      // T as private member data type.

      // T as return type of property.
      public T Data {
        get;
        set;
      }
    }

    private Node head;

    // constructor
    public GenericList() {
      head = null;
    }

    // T as method parameter type:
    public void AddHead(T t) {
      Node n = new Node(t);
      n.Next = head;
      head = n;
    }

    public IEnumerator<T> GetEnumerator() {
      Node current = head;

      while (current != null) {
        yield return current.Data;
        current = current.Next;
      }
    }
  }

}
